﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace ProjetS5
{
    public class Me : Player
    {
        public Me(Vector2 Position, Vector2 Orientation, byte Level, DB_CharacterRace Race, DB_CharacterClass CharacterClass, String Name)
            : base(Position, Orientation, Level, Race, CharacterClass, Name)
        {
            gameInterface = new Interface(1);
        }

        public Me(Database database, String Name, int Level, int Exp, Difficulty MaxDifficultyCompleted, int Life, int Mana, int RaceId, int ClassId, Interface GameInterface, List<List<int>> SelectedTalentsId, Dictionary<int, int> EquippedItemsId, Dictionary<Vector2, KeyValuePair<int, int>> InventoryItems, List<int> DoneQuestsId, List<int> DoneHFsId, Dictionary<int, List<int>> inLogQuestsId, Dictionary<int, List<int>> inProgressHFsId)
            : this(Vector2.Zero, Vector2.Zero, (byte)Level, null, null, Name)
        {
            experience = Exp;
            level = (byte)Level;
            maxDifficultyCompleted = MaxDifficultyCompleted;
            gameInterface = GameInterface;

            //vie & mana
            ChangeStat(calculatedStatistics, "vie", Life);
            ChangeStat(calculatedStatistics, "mana", Mana);

            characterRace = database.Datas.OfType<DB_CharacterRace>().Single(e => e.Identifier == RaceId);
            characterClass = database.Datas.OfType<DB_CharacterClass>().Single(e => e.Identifier == ClassId);

            //get doneQuests
            for (int i = 0; i < DoneQuestsId.Count; i++)
            {
                doneQuests.Add(database.Datas.OfType<DB_Quest>().Single(e => e.Identifier == DoneQuestsId[i]));
            }

            //get doneAchievements
            for (int i = 0; i < inLogQuestsId.Count; i++)
            {
                doneAchievements.Add(database.Datas.OfType<DB_Achievement>().Single(e => e.Identifier == DoneHFsId[i]));
            }
                
            //Dictionary<int, int> EquippedItemsId
            equipment = new Equipment();
            for (int i = 0; i < EquippedItemsId.Count; i++)
            {
                DB_Item dbItem = database.Datas.OfType<DB_Item>().Single(e => e.Identifier == EquippedItemsId[i]);
                DB_EquipmentSlot slot = database.Datas.OfType<DB_EquipmentSlot>().Single(e => e.Identifier == EquippedItemsId[i]);
                KeyValuePair<DB_EquipmentSlot, Item> item = new KeyValuePair<DB_EquipmentSlot, Item>(slot, new Item(dbItem.Identifier));
                equipment.equippedItems.Add(item);
            }

            //Dictionary<int, List<int>> inLogQuestsId
            foreach(KeyValuePair<int, List<int>> liste in inLogQuestsId)
            {
                DB_Quest dbQuest =  database.Datas.OfType<DB_Quest>().Single(e => e.Identifier == liste.Key);
                Dictionary<DB_Objective, int> objectives = new Dictionary<DB_Objective,int>();

                inLogQuests.Add(dbQuest, new Dictionary<DB_Objective, int>());

                for(int i = 0; i < dbQuest.Objectives.Count; i++)
                    inLogQuests.Last().Value.Add(dbQuest.Objectives[i], liste.Value[i]);
            }

            //Dictionary<int, List<int>> inProgressHFsId
            foreach (KeyValuePair<int, List<int>> liste in inProgressHFsId)
            {
                DB_Achievement achievement = database.Datas.OfType<DB_Achievement>().Single(e => e.Identifier == liste.Key);
                Dictionary<DB_Objective, int> objectives = new Dictionary<DB_Objective, int>();

                inProgressAchievements.Add(achievement, new Dictionary<DB_Objective, int>());

                for (int i = 0; i < achievement.Objectives.Count; i++)
                    inLogQuests.Last().Value.Add(achievement.Objectives[i], liste.Value[i]);
            }

            //List<List<int>> SelectedTalentsId
            foreach(List<int> liste in SelectedTalentsId)
            {
                foreach(int talent in liste)
                {

                }
            }

            //Dictionary<Vector2, KeyValuePair<int, int>> InventoryItems
            inventory = new Inventory(4, 10);
            foreach (KeyValuePair<Vector2, KeyValuePair<int, int>> liste in InventoryItems)
            {
                KeyValuePair<Item, int> item = new KeyValuePair<Item, int>(new Item(liste.Value.Key), liste.Value.Value);            
                inventory.items.Add(liste.Key, item);
            }
        }

        public Interface gameInterface;

        public void Move()
        {
            if (!isDead)
            {
                KeyboardState keyboardState = Keyboard.GetState();
                Vector2 direction = new Vector2(0);

                if (keyboardState.IsKeyDown(Keys.S) || keyboardState.IsKeyDown(Keys.Down))
                {
                    direction.Y += 1;
                }
                if (keyboardState.IsKeyDown(Keys.Q) || keyboardState.IsKeyDown(Keys.Left))
                {
                    direction.X -= 1;
                }
                if (keyboardState.IsKeyDown(Keys.D) || keyboardState.IsKeyDown(Keys.Right))
                {
                    direction.X += 1;
                }
                if (keyboardState.IsKeyDown(Keys.Z) || keyboardState.IsKeyDown(Keys.Up))
                {
                    direction.Y -= 1;
                }

                base.Move(direction, this.characterClass.Sprites);
            }
        }

        public ScreenMessage Cast(Ability ability, Character target)
        {
            ScreenMessage errorMessage = null;
            if (target == null) // Pas de cible.
            {
                errorMessage = new ScreenMessage("Il vous faut une cible pour effectuer cette action.");
            }
            else
            {
                if (target.friendshipLevelId == friendshipLevelId && target.friendshipLevelId != 2 || target.position == position) // Cible non compatible.
                {
                    errorMessage = new ScreenMessage("Cette cible n'est pas valide.");
                }
                else
                {
                    if (new Vector2(target.position.X - position.X, target.position.Y - position.Y).Length() > ability.ability.Range) // Cible trop loin.
                    {
                        errorMessage = new ScreenMessage("Vous etes trop loin de votre cible.");
                    }
                    else
                    {
                        if (casting.Key != null) // Déjà en train de faire autre chose.
                        {
                            errorMessage = new ScreenMessage("Une action est deja en cours.");
                        }
                        else
                        {
                            if(!isVisible(target.position)) // Cible dans le dos.
                            {
                                errorMessage = new ScreenMessage("Vous devez etre face a votre cible.");
                            }
                            else if (ability.ability.Cost != null)
                            {
                                foreach (KeyValuePair<DB_PointBar, int> kvpPBint in ability.ability.Cost) // Pas assez de ressource.
                                {
                                    if (kvpPBint.Value > pointBars[kvpPBint.Key])
                                    {
                                        errorMessage = new ScreenMessage("Vous n'avez pas assez de " + kvpPBint.Key.Name + " pour effectuer cette action.");
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return errorMessage;
        }
        public ScreenMessage Launch(Ability ability, Character target)
        {
            return new ScreenMessage("");
        }

        public void Draw(Game game, SpriteBatch spriteBatch, float targetDistance)
        {
            base.Draw(game, spriteBatch);
            foreach (InterfaceBar bar in gameInterface.bars)
            {
                bar.Draw(game, spriteBatch, targetDistance);
            }
        }
    }
}